#include "webwidget.h"
#include "control.h"
#include "javascript.h"


namespace webEvent
{
    /* all this GTK crap is making me sick, so there. singleton. */

    void load_commit (WebKitWebView* page, WebKitWebFrame* frame, gpointer data)
    {
        const gchar* uri = webkit_web_frame_get_uri(frame);
        if (uri)
        {
            std::string uristring = std::string (uri);
            std::string name = Control::Instance()->getNameFromURI(uristring);
            Control::Instance()->Shelf_consoleView->script("setPromptName('"+name+"')");
        }
           // gtk_entry_set_text (GTK_ENTRY (uri_entry), uri);
    }

    void load_finished (WebKitWebView* page, WebKitWebFrame* frame, gpointer data)
    {
                //hook capability report function
        JSStringRef str  = NULL;
        JSObjectRef func = NULL;
        JSContextRef jsctx = webkit_web_frame_get_global_context(webkit_web_view_get_main_frame(page));

        str = JSStringCreateWithUTF8CString("shelfReportCaps");
        func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::shelfReportCaps);
        JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);
        JSStringRelease(str);

        int id = Control::Instance()->getIdByView(page);
        std::stringstream getCaps;
        getCaps << //oh yea, inline javascript why the hell not
        "var linktags = document.getElementsByTagName(\"link\");\
        for (i = 0; i < linktags.length; i++)\
        {\
            if((linktags[i].rel == \"alternate\") && (linktags[i].type == \"application/rss+xml\"))\
            {\
                shelfReportCaps(\"rss\", linktags[i].title, linktags[i].href, \"" << id << "\");\
            }\
            if(linktags[i].rel == \"search\")\
            {\
                shelfReportCaps(\"search\", linktags[i].title, linktags[i].href, \"" << id << "\");\
            }\
        }";
        //webkit_web_view_execute_script(page, getCaps.c_str());
        Control::Instance()->getWebWidgetByView(page)->resetCapabilities();
        Control::Instance()->getWebWidgetByView(page)->script(getCaps.str());
    }

    void title_change(WebKitWebView* web_view, WebKitWebFrame* web_frame, const gchar* title, gpointer data)
    {
        std::string titlestring = std::string(title);
        std::cout <<"got new title: "<<titlestring<<"\n";
        //std::string name = Control::Instance()->Shelf_webView->getName();
        //Control::Instance()->Shelf_consoleView->script("setPromptName('"+name+"')");
    }

    void navigation_requested(WebKitWebView* thisWebView, WebKitWebFrame* thisWebFrame, WebKitNetworkRequest* thisnetrequest)
    {
        std::string scriptstring = "statusPrint(\"opening: ";
        scriptstring += webkit_network_request_get_uri(thisnetrequest);
        scriptstring += "\")";
        Control::Instance()->Shelf_consoleView->script(scriptstring);
        std::cout <<"navigation requested: "<< webkit_network_request_get_uri(thisnetrequest) << "\n";
    }

    void link_hover(WebKitWebView* webView, const char* title, const char* uri, gpointer data)
    {
        if(webView == Control::Instance()->Shelf_consoleView->getWebView())
        return;

            if(uri)
            {
                std::string scriptstring = "statusPrint(\"";
                scriptstring += uri;
                scriptstring += "\")";
                Control::Instance()->Shelf_consoleView->script(scriptstring);
            }
            else
            {
                Control::Instance()->Shelf_consoleView->script("statusPrint(\"\")");
            }
    }
}//namespace webEvent

WebWidget::WebWidget()
{
    webView = WEBKIT_WEB_VIEW (webkit_web_view_new ());
    gtkwidget = Glib::wrap((GtkWidget*)webView);

    g_signal_connect (G_OBJECT (webView), "hovering-over-link", G_CALLBACK (webEvent::link_hover), webView);
    g_signal_connect (G_OBJECT (webView), "navigation-requested", G_CALLBACK (webEvent::navigation_requested), webView);
    g_signal_connect (G_OBJECT (webView), "title-changed", G_CALLBACK (webEvent::title_change), webView);
    g_signal_connect (G_OBJECT (webView), "load-committed", G_CALLBACK (webEvent::load_commit), webView);
    g_signal_connect (G_OBJECT (webView), "load-finished", G_CALLBACK (webEvent::load_finished), webView);
    /*
    g_signal_connect (G_OBJECT (web_view), "title-changed", G_CALLBACK (title_change_cb), web_view);
    g_signal_connect (G_OBJECT (web_view), "load-progress-changed", G_CALLBACK (progress_change_cb), web_view);
    g_signal_connect (G_OBJECT (web_view), "load-committed", G_CALLBACK (load_commit_cb), web_view);
    g_signal_connect (G_OBJECT (web_view), "hovering-over-link", G_CALLBACK (link_hover_cb), web_view);
    */
}

void WebWidget::navigationRequested(WebKitWebView* thisWebView, WebKitWebFrame* thisWebFrame, WebKitNetworkRequest* thisnetrequest)
{
    std::cout << "navigation request signal received\n";
}

Gtk::Widget* WebWidget::getWidget()
{
    return gtkwidget;
}


WebKitWebView* WebWidget::getWebView()
{
    return webView;
}

JSContextRef WebWidget::getJavascriptContext()
{
    return webkit_web_frame_get_global_context(webkit_web_view_get_main_frame(webView));

}

void WebWidget::hookConsoleFunctions()
{
    JSStringRef str  = NULL;
    JSObjectRef func = NULL;
    JSContextRef jsctx = getJavascriptContext();//webkit_web_frame_get_global_context(webkit_web_view_get_main_frame(webView));

    str = JSStringCreateWithUTF8CString("newShelf");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::newShelf);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("listShelves");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::listShelves);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("setConsoleSize");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::setConsoleSize);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("isCommand");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::isCommand);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("openInShelf");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::openInShelf);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("isURI");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::isURI);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("shelfInfo");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::shelfInfo);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("loadPlugin");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::loadPlugin);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("switchShelf");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::switchShelf);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);

    str = JSStringCreateWithUTF8CString("hideConsole");
    func = JSObjectMakeFunctionWithCallback(jsctx, str, javaScript::hideConsole);
    JSObjectSetProperty(jsctx, JSContextGetGlobalObject(jsctx), str, func, kJSPropertyAttributeNone, NULL);
    JSStringRelease(str);

}
void WebWidget::script(std::string script)
{
    webkit_web_view_execute_script(webView, script.c_str());
}

std::string WebWidget::listCapabilities()
{
    std::stringstream caps;
    if(!feeds.empty())
    {
        for(unsigned int i = 0; i< feeds.size(); i++)
        {
            caps << "<img src='feedicon.png'> " << feeds[i].title << "<br>";
        }
    }
    if(!searches.empty())
    {
        for(unsigned int i = 0; i< searches.size(); i++)
        {
            caps << "<img src='searchicon.png'> " << searches[i].title << "<br>";
        }
    }
    return caps.str();
}

void WebWidget::notifyCapabilities()
{
    Control::Instance()->Shelf_consoleView->script("clearNotifications()");
    if(!feeds.empty())
    {
        std::stringstream feedhover;
        if(feeds.size() > 1)
        {
            feedhover << feeds.size() << " feeds available";
        }
        else
        {
            feedhover << "feed available: " << feeds[0].title;
        }

        Control::Instance()->addNotification("feedicon.png", feedhover.str(), "consolePrint(\" + '\"subscribe to feed?\"' + \")");
    }
    if(!searches.empty())
    {
        std::stringstream searchhover;
        if(searches.size() > 1)
        {
            searchhover <<  searches.size() << " search engines available";
        }
        else
        {
            searchhover << "search available: " << searches[0].title;
        }
        Control::Instance()->addNotification("searchicon.png", searchhover.str(), "consolePrint(\" + '\"set default search engine?\"' + \")");
    }
}
void WebWidget::resetCapabilities()
{
    feeds.clear();
    searches.clear();
}
void WebWidget::addCapability(std::string cap, std::string title, std::string href)
{
    if(cap == "rss")
    {
        feeds.push_back(Capability(cap, title, href));
        return;
    }
    if(cap == "search")
    {
        searches.push_back(Capability(cap, title, href));
        return;
    }
    std::cout << "uh oh! no idea what " << cap << "is!\n";
    //not implemented. harhar.
    /*
    if(cap == "rss")
    {
        Control::Instance()->addNotification("feedicon.png", "this page has an rss feed", "consolePrint(\" + '\"subscribe to feed?\"' + \")");
    }
    if(cap == "search")
    {
        Control::Instance()->addNotification("searchicon.png", "this page has an openSearch plugin", "consolePrint(\" + '\"set default search engine?\"' + \")");
    }*/


}

std::string WebWidget::html(std::string html)
{
    webkit_web_view_load_html_string(webView, html.c_str(), "shelf://Shelf/");
    return "shelf";
    //webkit_web_view_load_html_string(webView, html.c_str(), "file:///home/armen/projects/shelf/shelfhome.html");
}

std::string WebWidget::open(std::string uri)
{
   // std::cout <<"web open\n";
    webkit_web_view_open (webView, uri.c_str());
    return Control::Instance()->getNameFromURI(uri);
}

std::string WebWidget::getURI()
{
    WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
    if(webkit_web_frame_get_uri(frame))
    {
        std::string uri = std::string(webkit_web_frame_get_uri(frame));
        return uri;
    }
    else
    {
        return "unknown";
    }
}
std::string WebWidget::getTitle()
{
    WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
    if(webkit_web_frame_get_title(frame))
    {
        std::string title = std::string(webkit_web_frame_get_title(frame));
        return title;
    }
    else
    {
        return "unknown";
    }
}

std::string WebWidget::getName()
{
    WebKitWebFrame *frame = webkit_web_view_get_main_frame(webView);
    //std::cout << "uri? " << webkit_web_frame_get_uri(frame)<<"\n";
    if(!webkit_web_frame_get_uri(frame))return "unknown";

    std::string uri = std::string(webkit_web_frame_get_uri(frame));
    return Control::Instance()->getNameFromURI(uri);
}
